package jd.monitor.jbtrace;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.sun.btrace.client.Main;

public class BtraceWrap {
	
	
	private String scriptFile;
	ExecutorService executorService = Executors.newSingleThreadExecutor();
	WorkRunnable work = new WorkRunnable();
	public BtraceWrap(String scriptFile){
		this.scriptFile = scriptFile;
		executorService.execute(work);
		
	}
	
	class StreamWatch extends Thread {  
		InputStream is;  
		String type;  
		List<String> output = new ArrayList<String>();  
		boolean debug = false;  
		  
		StreamWatch(InputStream is, String type) {  
		   this(is, type, false);  
		}  
		  
		StreamWatch(InputStream is, String type, boolean debug) {  
		   this.is = is;  
		   this.type = type;  
		   this.debug = debug;  
		}  
		  
		public void run() {  
		   try {  
		    PrintWriter pw = null;  
		    InputStreamReader isr = new InputStreamReader(is);  
		    BufferedReader br = new BufferedReader(isr);  
		    String line = null;  
		    while ((line = br.readLine()) != null) {  
		     output.add(line);  
		     if (debug)  
		      System.out.println(type + ">" + line);  
		    }  
		    if (pw != null)  
		     pw.flush();  
		   } catch (IOException ioe) {  
		    ioe.printStackTrace();  
		   }  
		}  
		  
		public List<String> getOutput() {  
		   return output;  
		}  
		}  
	
	
	class WorkRunnable implements Runnable{

		@Override
		public void run() {
			
			String javaHome = System.getProperty("java.home");
			String clientPath = "/btrace-client.jar";
			String tmp = BtraceWrap.class.getProtectionDomain().getCodeSource().getLocation().getFile();
			tmp = tmp.substring(0, tmp.lastIndexOf("/"));
			if(System.getProperty("os.name").toLowerCase().startsWith("windows")){
				tmp = tmp.substring(1);	
			}
			clientPath = tmp + clientPath;
			System.out.println("clientPath = "+clientPath);
//			String tmp = BtraceWrap.class.getClassLoader().getResource("jd/monitor/jbtrace").toString();
//			tmp = tmp.substring(0, tmp.indexOf("!"));
//			tmp = tmp.substring("jar:".length(), tmp.lastIndexOf("/"));
//			try {
//				clientPath = new File(new URI(clientPath)).getAbsolutePath();
//			} catch (URISyntaxException e1) {
//				e1.printStackTrace();
//			}
			String toolsJar = javaHome+"/../lib/tools.jar" ;
			String scriptPath = scriptFile;
			if(!scriptFile.contains("/")){
				scriptPath = BtraceWrap.class.getClassLoader().getResource(scriptFile).getPath();
				if(System.getProperty("os.name").toLowerCase().startsWith("windows")){
					scriptPath = scriptPath.substring(1);
				}
			}
			
			List<String> list = new ArrayList<String>();
			String java = javaHome + File.separator + "../bin" + File.separator + "java";
			list.add(java);
//			list.add("-Dcom.sun.btrace.debug=true");
			list.add("-Dcom.sun.btrace.unsafe=true");
		    list.add("-cp");  
		    list.add(clientPath + File.pathSeparator + toolsJar);  
		    list.add(Main.class.getName());
//		    list.add("-v");
//		    list.add("-u");
		    String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
		    list.add(pid);
		    list.add(scriptPath);
			ProcessBuilder pb = new ProcessBuilder(list );
			try {
				Process p = pb.start();
				System.out.println(pb.command());  
			    // process error and output message  
			    StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),  
			      "ERROR");  
			    StreamWatch outputWatch = new StreamWatch(p.getInputStream(),  
			      "OUTPUT",true);  
			    // start to watch  
			    errorWatch.start();  
			    outputWatch.start();  
			    //wait for exit  
			    int exitVal = p.waitFor();  
			    //print the content from ERROR and OUTPUT  
			    System.out.println("ERROR: " + errorWatch.getOutput());  
			    System.out.println("OUTPUT: " + outputWatch.getOutput());  
			    System.out.println("the return code is " + exitVal);  			
			} catch (Exception e) {
				e.printStackTrace();
			}

		}
		
	}
	
}
